import JSEncrypt from "jsencrypt"
/**
 * @method updateFontSize
 * @returns 返回当前fontsize
 */
export function updateFontSize() {
    let availWidth = window.screen.width
    if (!availWidth) {
        return 0
    }
    availWidth = availWidth < 1920 ? 1920 : availWidth
    let fontSize = parseFloat(100 / 1920 * availWidth, 10).toFixed(2)
    let root = document.documentElement || document.body
    root.style.fontSize = fontSize + 'px'
    return fontSize
}

/**
 * @method TimeFormat（）格式化时间
 * @param {Date} time 需要格式化的时间 Date对象
 * @param {String} format 需要格式化成的格式
 */
export function timeFormat(time, format) {
    let [year, month, day, hour, minutes, seconds] = [
        time.getFullYear(),
        (time.getMonth() + 1) >= 10 ? (time.getMonth() + 1) : '0' + (time.getMonth() + 1),
        time.getDate() >= 10 ? time.getDate() : '0' + time.getDate(),
        time.getHours() >= 10 ? time.getHours() : '0' + time.getHours(),
        time.getMinutes() >= 10 ? time.getMinutes() : '0' + time.getMinutes(),
        time.getSeconds() >= 10 ? time.getSeconds() : '0' + time.getSeconds()
    ]
    switch (format) {
        case 'Y-M-D':
            return `${year}-${month}-${day}`
        case 'Y.M.D':
            return `${year}.${month}.${day}`
        case '年-月-日 H:M:S':
            return `${parseInt(year, 10)}${temp.$t('Year')}${parseInt(month, 10)}${temp.$t('Month')}${parseInt(day, 10)}${temp.$t('day')} ${hour}:${minutes}:${seconds}`
        case `年-月-日`:
            return `${parseInt(year, 10)}${temp.$t('Year')}${parseInt(month, 10)}${temp.$t('Month')}${parseInt(day, 10)}${temp.$t('day')}`
        case 'H:M:S':
            return hour + ':' + minutes + ':' + seconds
        default:
            return `${year}-${month}-${day} ${hour}:${minutes}:${seconds}`
    }
}
/**
 * @method windowToCanvas() 将鼠标相对屏幕的坐标，转化成canvas画布上的实际坐标
 * @param {Object} canvas 对象
 * @param {Number} x 相对屏幕的横坐标
 * @param {Number} y 相对屏幕的纵坐标
 * @return {param} 返回实际坐标对象
 */
export function windowToCanvas(canvas, x, y) {
    let rect = canvas.getBoundingClientRect()
    return {
        x: (x - rect.left) * (canvas.width / rect.width),
        y: (y - rect.top) * (canvas.height / rect.height)
    }
}
/**
 * @method toBlob() base64图片转化成blob、file类型格式
 * @param {Object} base64Data base64数据
 * @return
 */
export function toBlob(base64Data) {
    let byteString = ''
    if (base64Data.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(base64Data.split(',')[1])
    else
        byteString = unescape(base64Data.split(',')[1]);
    let mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0]
    let ab = new ArrayBuffer(byteString.length)
    let ia = new Uint8Array(ab)
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i)
    }
    return new Blob([ia], {
        type: mimeString
    })
}
/**
 * @method fileToDataURL() 上传图片的格式转为base64
 * @param {file} imgFile 要转换的文件
 */
export function fileToDataURL(imgFile) {
    // 选择的文件是图片
    if (!imgFile || imgFile.type.indexOf('image') !== 0) {
        return
    }
    return new Promise((resolve, reject) => {
        // 压缩图片需要的一些元素和对象
        var reader = new FileReader()
        // 文件base64化，以便获知图片原始尺寸
        reader.onload = function (e) {
            resolve(e.target.result)
        }
        reader.onerror = function (e) {
            reject(e)
        }
        // 选择的文件是图片
        reader.readAsDataURL(imgFile)
    })
}
/**
 * @method countBaseSize() 计算base64图片大小
 * @param base64url base64的图片编码
 */
export function countBaseSize(base64url) {
    //获取base64图片大小，返回MB数字
    let str = base64url.replace('data:image/png;base64,', '')
    let equalIndex = str.indexOf('=')
    if (str.indexOf('=') > 0) {
        str = str.substring(0, equalIndex);
    }
    let strLength = str.length
    let fileLength = parseInt(strLength - (strLength / 8) * 2, 10)
    // 由字节转换为MB
    let size = ""
    size = (fileLength / (1024 * 1024)).toFixed(2)
    return size
}
/**
 * @method getImageBase64() 普通图片转化成base64
 * @param {String} ext 图片的类型
 */
export function getImageBase64(img, ext) {
    let canvas = document.createElement("canvas")
    canvas.width = img.width
    canvas.height = img.height
    let ctx = canvas.getContext("2d")
    ctx.drawImage(img, 0, 0, img.width, img.height)
    let dataURL = canvas.toDataURL("image/" + ext)
    canvas = null
    return dataURL
}

/**
 * @method addZero() 对于小于0的进行补零操作
 * @return {String} 补0后的数据
 */
export function addZero(time) {
    let newTime = time > 9 ? time : '0' + time
    return newTime
}
/**
 * @method toStringBySecond 将秒转成时分秒
 * @param {String} second 要转换的秒
 * @param {String} typeStr = 'h:m:s' || '' ? 'h:m:s' : '时:分:秒'
 */
export function toStringBySecond(second, typeStr = 'h:m:s') {
    const sec = second < 60 ? this.addZero(second) : this.addZero(second % 60)
    const min = second < 60 ? '00' : second < 3600 ? this.addZero(parseInt(second / 60, 10)) : this.addZero(parseInt(second % 3600 / 60, 10))
    const hour = this.addZero(parseInt(second / 3600, 10))
    return typeStr === 'h:m:s' ? `${hour}:${min}:${sec}` : `${hour}${temp.$t('hour')}${min}${temp.$t('min')}${sec}${temp.$t('sec')}`
}
/**
 * @method toStringBySecond 将秒转成分秒
 * @param {String} second 要转换的秒
 * @param {String} typeStr = 'm:s' || '' ? 'm:s' : '分:秒'
 */
export function toStringBySeconds(second, typeStr = 'm:s') {
    if (second === 0 || second === '') {
        return ''
    }
    const sec = second < 60 ? this.addZero(second) : this.addZero(second % 60)
    const min = second < 60 ? '00' : second < 3600 ? this.addZero(parseInt(second / 60, 10)) : this.addZero(parseInt(second % 3600 / 60, 10))
    return typeStr === 'm:s' ? `${min}:${sec}` : `${min}${temp.$t('min')}${sec}${temp.$t('sec')}`
}
/**
 * @method arrHeavy() 数组对象去重
 * @param sourceArr 原数组
 * @param keyArray 所要以什么字段为参考的数组
 */
export function arrHeavy(sourceArr, keyArray) {
    let obj = {}
    let arr = []
    sourceArr.forEach((d) => {
        let str = ''
        keyArray.forEach((key) => {
            str += d[key] || d[key] === 0 ? d[key] + '$' : ''
        })
        if (!obj[str]) {
            arr.push(d)
            obj[str] = 1
        }
    })
    return arr
}
/**
 * @method getCodeFromArr() 从数组对象中获取某个属性，组成新的数组
 * @param {Array} sourceArr 数组对象
 * @param {Array} attr 希望从arr中获取的属性
 */
export function getCodeFromArr(sourceArr, attr) {
    let arr = []
    sourceArr.forEach((item) => {
        let param = {}
        attr.forEach((key) => {
            param[key] = item[key]
        })
        arr.push(param)
    })
    return arr
}
/**
 * @method guid() 生成uuid
 */
export function guid() {
    function s4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
    }
    return (s4() + s4() + "-" + s4() + "-" + s4() + "-" + s4() + "-" + s4() + s4() + s4())
}
/**
 * @method getUTCTime()
 */
export function getUTCTime() {
    var currentTime = new Date()
    return currentTime.getTime() + currentTime.getTimezoneOffset() * 60000
}
/**
 * copyText() 将文案复制到黏贴板
 * @param {String} text 要复制的文案
 */
export function copyText(text) {
    const input = document.createElement('input')
    input.style.position = 'absolute'
    input.style.zIndex = -10
    document.body.appendChild(input)
    input.setAttribute('value', text)
    input.select()
    document.execCommand('copy')
    document.body.removeChild(input)
}
/**
 * @method downloadFile() post方式导出excel
 * @param {String} url 接口
 * @param {Json} data 数据
 */
export function downloadFile(url, data) {
    const body = document.getElementsByTagName('body')[0]
    const form = document.createElement('form')
    form.method = 'POST'
    form.action = window.location.origin + '/' + url
    form.style.display = 'none'
    for (var key in data) {
        var param = document.createElement('input')
        param.type = "hidden"
        param.name = key
        param.value = data[key]
        form.appendChild(param)
    }
    body.appendChild(form)
    form.submit()
    body.removeChild(form)
}
export function downLoad(url, data, fileName) {
    var param = ''
    for (var key in data) {
        param += key + "=" + data[key] + "&"
    }
    param = param.slice(0, param.length - 1)
    window.location.href = url + "?" + param + "&token=" + localStorage.getItem('token') + "&userId=" + localStorage.getItem('userId') + "&userName=" + localStorage.getItem('userName')
}
/**
 * @method countLen()计算flex布局需补白个数
 * @param {Object} boxDom 列表容器
 * @param {Number} pW 列表容器的padding-right和padding-left宽度
 * @param {Number} liW 列表中具体元素的宽度
 * @param {Object} data v-for 在列表中渲染的数据源
 * @return {Object} data 补白后数据
 */
export function countLen(boxDom, pW, liW, data) {
    let arr = []
    data.forEach((item) => {
        if (JSON.stringify(item) !== '{}') arr.push(item)
    })
    //这里的40是父容器的左右padding和
    let w = boxDom.offsetWidth - pW
    let g = parseInt(w / liW, 10)
    let len = arr.length
    //末尾补全适应flex布局
    if (len > 0) {
        for (var i = 0; i < (g - len % g); i++) {
            arr.push({})
        }
    }
    return arr
}
/**
 * @method getMonthDays 获取某个月份的天数
 * @param {Number} month 月份
 * @param {Number} year 年份
 * @return {Number} days 当月天数
 */
export function getMonthDays(month, year) {
    let [m, y] = [month, year]
    let date = new Date()
    if (!month) m = date.getMonth() + 1
    if (!year) y = date.getFullYear()
    m = parseInt(m, 10)
    let d = new Date(m, y, 0)
    return d.getDate()
}
/**
 * @method strMapToObj map转化为对象
 * @param {Map} strMap 待转换的Map
 * @returns {Object} obj 转换结果
 */
export function strMapToObj(strMap) {
    let obj = {}
    for (let [k, v] of strMap) {
        obj[k] = v
    }
    return obj
}
/**
 * @method objToStrMap 对象转化为map
 * @param {Object} obj 待转换的Object
 * @returns {Map} strMap 转换结果
 */
export function objToStrMap(obj) {
    let strMap = new Map()
    for (let k of Object.keys(obj)) {
        strMap.set(k, obj[k])
    }
    return strMap
}
/**
 * @method mapToJson Map转换Json
 * @param {Object} obj 待转换的Object
 * @returns {String} 转换结果jSON
 */
export function mapToJson(map) {
    return JSON.stringify(strMapToObj(map))
}
/**
 * @method jsonToMap Json转换Map
 * @param {String} jsonStr 待转换的json
 * @returns {Map} 转换结果Map
 */
export function jsonToMap(jsonStr) {
    return objToStrMap(JSON.parse(jsonStr))
}
/**
 * @method getDataType() 判定数据类型
 * @param {any} object 传入的数据类型
 * @returns {string} 数据类型，均为小写
 */
export function getDataType(object) {
    // IE9下调用toString.call(undefined)报错
    if (typeof object === 'undefined') {
        return 'undefined'
    }
    let map = {
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Boolean]': 'boolean',
        '[object Object]': 'object',
        '[object Array]': 'array',
        '[object RegExp]': 'regExp',
        '[object Function]': 'function',
        '[object Promise]': 'promise',
        '[object GeneratorFunction]': 'generatorFunction',
        '[object Null]': 'null',
    }
    let typeString = ''
    if (object instanceof Element) {
        typeString = 'element'
    } else {
        typeString = map[Object.prototype.toString.call(object)]
    }
    return typeString
}
/**
 * 判定两个对象是否相等，包含子对象（所有键和键值都一致）
 * @param {object} object1 需要比较的对象
 * @param {object} object2 需要比较的对象
 * @returns {boolean}
 */
export function compareObject(object1, object2) {
    if (typeof (object1) !== 'object' || typeof (object2) !== 'object') {
        throw new Error('Please enter object params.')
    }
    const aProps = Object.keys(object1)
    const bProps = Object.keys(object2)
    if (aProps.length !== bProps.length) {
        return false
    }
    for (let i = 0; i < aProps.length; i++) {
        let propName = aProps[i]
        let propA = object1[propName]
        let propB = object2[propName]
        if (typeof (propA) === 'object') {
            if (!this.isObjectValueEqual(propA, propB)) {
                return false
            }
        } else if (propA !== propB) {
            return false
        }
    }
    return true
}
/**
 * @method toObject Json转换成对象
 * @description 如果传入的是JSON则转成对象，如果是非JSON，则直接返回
 * @param {object | string} 传入的对象
 */
export function toObject(data) {
    let newData = {}
    try {
        newData = JSON.parse(data)
    } catch (e) {
        newData = data
    }
    return newData
}
/**
 * 判断是不是ie8\9\10等低版本浏览器
 * @method isIELowVersion
 * @returns {boolean} 是否是IE
 */
export function isIELowVersion() {
    if (!!window.ActiveXObject || "ActiveXObject" in window) {
        if (navigator && navigator.appName === "Microsoft Internet Explorer" &&
            (navigator.appVersion.match(/8./i) || navigator.appVersion.match(/9./i) || navigator.appVersion.match(/10./i))) {
            return true
        }
    }
    return false
}
/**
 * 判断是不是ie11浏览器
 * @method isIE11
 * @returns {boolean} 是否是IE11
 */
export function isIE11() {
    if (!!window.ActiveXObject || "ActiveXObject" in window) {
        if (navigator && navigator.appVersion.match(/11./i)) {
            return true;
        }
    }
    return false;
}
/**
 * 判断当前的浏览器是否满足版本需求
 *
 * @method getBrowserInfo
 * @param {Number} vie 需要的ie最低版本，不支持则为0
 * @param {Number} vchrome 需要的chrome最低版本，不支持则为0
 * @param {Number} vff 需要的firefox最低版本，不支持则为0
 * @returns {Boolean}
 */
export function getBrowserInfo(vchrome, vff, vie) {
    const agent = navigator.userAgent.toLowerCase()
    const regStr_ie = /msie [\d.]+/gi
    const regStr_ff = /firefox\/[\d.]+/gi
    const regStr_chrome = /chrome\/[\d.]+/gi
    let stutus = false
    let str = ''
    if (agent.indexOf('msie') > 0 && vie) {
        str = (agent.match(regStr_ie) + '').replace(/[^0-9.]/ig, '')
        stutus = str.split('.')[0] - vie >= 0 ? true : false
    }
    if ((!!window.ActiveXObject || "ActiveXObject" in window) && agent.indexOf('msie') < 0) {
        stutus = true
    }
    if (agent.indexOf('chrome') > 0 && vchrome) {
        str = (agent.match(regStr_chrome) + '').replace(/[^0-9.]/ig, '')
        stutus = str.split('.')[0] - vchrome >= 0 ? true : false
    }
    if (agent.indexOf('firefox') > 0 && vff) {
        str = (agent.match(regStr_ff) + '').replace(/[^0-9.]/ig, '')
        stutus = str.split('.')[0] - vff >= 0 ? true : false
    }
    return stutus
}
/**
 * 深度克隆对象，不支持对象内方法的克隆
 * @param {Objectany} source 待拷贝对象
 * @returns {Object}
 */
export function deepClone(source) {
    return JSON.parse(JSON.stringify(source))
}

//深拷贝
export function deepCopy(obj) {
    // Hash表 记录所有的对象引用关系
    let map = new WeakMap();
    function dp(obj) {
        let result = null;
        let keys = null,
            key = null,
            temp = null,
            existObj = null;

        existObj = map.get(obj);
        // 如果这个对象已被记录则直接返回
        if (existObj) {
            return existObj;
        }
        keys = Object.keys(obj);
        result = {};
        // 记录当前对象
        map.set(obj, result);
        for (let i = 0; i < keys.length; i++) {
            key = keys[i];
            temp = obj[key];
            // 如果字段的值也是一个对象则递归复制
            if (temp && (Object.prototype.toString.call(temp) === '[object Array]' || Object.prototype.toString.call(temp) === '[object Object]')) {
                result[key] = dp(temp);
            } else {
                // 否则直接赋值给新对象
                result[key] = temp;
            }
        }
        return result;
    }
    return dp(obj);
}

/**
 * @method setStorage
 * @param key
 * @param value
 * @param expiredTime 过期时间 单位ms
 * @return 返回
 */
export function setStorage(key, value, expiredTime) {
    if (expiredTime === 0 || expiredTime === null) {
        localStorage.setItem(key, value)
    } else {
        localStorage.setItem(key, value)
        localStorage.setItem(key + expiredTime, expiredTime)
        localStorage.setItem(key + expiredStartTime, new Date().getTime())
    }
}
/**
 * @method getStorage
 * @param key
 * @return key存在，返回对象；不存在，返回null
 */
export function getStorage(key) {
    const expiredTime = localStorage.getItem(key + expiredTime)
    const expiredStartTime = localStorage.getItem(key + expiredStartTime)
    const nowDate = new Date().getTime()
    const cutNum = Number(expiredStartTime) + Number(expiredTime)
    return nowDate < cutNum ? JSON.parse(localStorage.getItem(key)) : null
}

/**
 * @method getStorage 清除key
 * @param key
 * @return key存在，返回对象；不存在，返回null
 */
export function removeStorage(key) {
    localStorage.removeItem(key + expiredTime)
    localStorage.removeItem(key + expiredStartTime)
    localStorage.removeItem()
}
/**
 * @method getStorage 更新过期时间
 * @param key
 *  @param expiredTime 过期时间 单位ms
 * @return *
 */
export function expired(key, expiredTime) {
    if (getStorage(key) !== null) {
        localStorage.setItem(key + expiredTime, expiredTime)
    }
}
/**
 * @method  subStr 多出部分加...
 * @param str 需要转化的字符串
 * @param n 需要显示的字符长度
 */
export function subStr(str, n) {
    if (str) {
        let r = /[^\x00-\xff]/g;
        if (str.replace(r, "mm").length <= n) { return str }
        let m = Math.floor(n / 2);
        for (let i = m; i < str.length; i++) {
            if (str.substr(0, i).replace(r, "mm").length >= n) {
                return str.substr(0, i) + "...";
            }
        }
    }
    return str;
}
/**
 * @method formatData 多出部分加...
 * @param text 需要转化的字符串
 * @param len 需要显示的字符长度
 */
export function formatData(text, len = 10) {
    let str = text
    if (str && str.length > len) {
        str = str.substring(0, len) + '...'
    }
    return str
}
/**
 * @method nReplace 每隔n个字符加入操作符
 * @param text 需要转化的字符串
 * @param len 字符串的长度
 * @param op 操作符'\n'等
 */
export function nReplace(text, len, op = '\n') {
    let str = text
    let re = new RegExp(`(.{${len}})`, 'g')
    if (str && str.length > len) {
        str = str.replace(re, `$1${op}`)
    }
    return str
}
/**
 * @method simpleToArray 简单数据转化成ztree数据
 * @param params simple设置
 ***/
export function simpleToArray(sNodes, params = {}) {
    var i, l,
        key = params.idKey || 'id',
        val = 'value',
        kk = 'key',
        title = 'title',
        name = params.nameKey || 'name',
        parentKey = params.parentKey || 'pId',
        childKey = 'children'
    if (!key || !sNodes) return [];
    if (Object.prototype.toString.apply(sNodes) === "[object Array]") {
        var r = [];
        var tmpMap = {};
        for (i = 0, l = sNodes.length; i < l; i++) {
            tmpMap[sNodes[i][key]] = sNodes[i];
            sNodes[i][kk] = sNodes[i][val] = sNodes[i][key]
            sNodes[i][title] = sNodes[i][name]
        }
        for (i = 0, l = sNodes.length; i < l; i++) {
            if (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] !== sNodes[i][parentKey]) {
                if (!tmpMap[sNodes[i][parentKey]][childKey])
                    tmpMap[sNodes[i][parentKey]][childKey] = []
                tmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i])
            } else {
                r.push(sNodes[i])
            }
        }
        return r
    }
    return [sNodes]
}
// 组织树数据格式化
export function transformData(tree) {
    let arr = [];
    if (!!tree && tree.length !== 0) {
        tree.forEach(item => {
            let obj = {};
            obj.title = item.name;
            obj.key = item.id;
            obj.value = item.id;
            obj.checked = item.checked;
            obj.children = this.transformData(item.children); // 递归调用
            arr.push(obj);
        });
    }
    return arr;
}

//AES encode
export function rEncode(key, str) {
    if (!str) return ''
    let key1 = CryptoJS.enc.Utf8.parse(key)
    let e = CryptoJS.AES.encrypt(str, key1, { iv: key1, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
    return e.ciphertext.toString()
}
//AES decode
export function rDecode(key, rStr) {
    if (!rStr) return ''
    let key1 = CryptoJS.enc.Utf8.parse(key)
    let a = CryptoJS.enc.Hex.parse(rStr)
    let b = CryptoJS.enc.Base64.stringify(a)
    let c = CryptoJS.AES.decrypt(b, key1, { iv: key1, mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
    return c.toString(CryptoJS.enc.Utf8)
}

/**
 * @method arraySortByKey() 针对数组对象做排序
 * @param {array} list 需要排序的数组对象
 * @param {String} key 排序的基准key值
 */
export function arraySortByKey(list, key) {
    function charCompare(charA, charB) {
        // 谁为非法值谁在前面
        if (charA === undefined || charA === null || charA === '' || charA === ' ' || charA === '　') {
            return -1
        }
        if (charB === undefined || charB === null || charB === '' || charB === ' ' || charB === '　') {
            return 1
        }
        // 如果都为英文或者都为汉字则直接对比
        if ((notChinese(charA) && notChinese(charB)) || (!notChinese(charA) && !notChinese(charB))) {
            return charA.localeCompare(charB)
        } else {
            // 如果不都为英文或者汉字，就肯定有一个是英文，如果a是英文，返回-1，a在前，否则就是b是英文，b在前
            if (notChinese(charA)) {
                return -1
            } else {
                return 1
            }
        }
    }

    function notChinese(char) {
        const charCode = char.charCodeAt(0)
        return charCode >= 0 && charCode <= 128
    }

    if (list === undefined || list === null) return []
    list.sort((a, b) => {
        let strA = a[key]
        let strB = b[key]
        // 谁为非法值谁在前面
        if (strA === undefined || strA === null || strA === '' || strA === ' ' || strA === '　') {
            return -1
        }
        if (strB === undefined || strB === null || strB === '' || strB === ' ' || strB === '　') {
            return 1
        }
        // 如果a和b中全部都是汉字，或者全部都非汉字
        if ((strA.split('').every(char => notChinese(char)) && strB.split('').every(char => notChinese(char))) ||
            (strA.split('').every(char => !notChinese(char)) && strB.split('').every(char => !notChinese(char)))) {
            return strA.localeCompare(strB)
        } else {
            const charAry = strA.split('')
            for (const i in charAry) {
                if ((charCompare(strA[i], strB[i]) !== 0)) {
                    return charCompare(strA[i], strB[i])
                }
            }
            // 如果通过上面的循环对比还比不出来，就无解了，直接返回-1
            return -1
        }
    })
    return list
}
/**
 * @desc 比较两个对象返回差异部分
 * @param {object} modify 修改后的数据
 * @param {object} source 最初的数据
 */
export function diffData(modify, source) {
    const diff = {}
    for (let key in modify) {
        if (modify[key] !== source[key]) {
            diff[key] = modify[key]
        }
    }
    return diff
}

//节流, 一段时间内只执行第一次请求
export const throttle = (fn, delay = 1000) => {
    let isThtottle = true
    return () => {
        if (!isThtottle) return
        isThtottle = false
        setTimeout(() => {
            fn()
            isThtottle = true
        }, delay)
    }
}

//防抖, 一段时间内只执行最后一次请求
export const debounce = (fn, delay = 1000) => {
    let timer = null
    return () => {
        timer && clearTimeout(timer)
        timer = setTimeout(() => {
            fn();
        }, delay)
    }
}

//中断请求
export function cancelRequest(that, paramName = 'source') {
    if (typeof that[paramName] === 'function') {
        that[paramName]()
    }
}
//忽略大小写判断是否相同
export function coverString(subStr, str) {
    let reg = new RegExp(subStr, 'ig')
    return reg.test(str)
}
/**
 * @desc 换肤方法
 * @param {object} colorData 需要替换颜色的键值对
 */
export function changeColors(colorData, client = window, doc = document) {
    function cssReady(fn, link) {
        var d = doc,
            t = d.createStyleSheet,
            r = t ? 'rules' : 'cssRules',
            s = t ? 'styleSheet' : 'sheet',
            l = d.getElementsByTagName('link');
        // passed link or last link node
        link || (link = l[l.length - 1]);

        function check() {
            try {
                return link && link[s] && link[s][r] && link[s][r][0];
            } catch (e) {
                return false;
            }
        }
        (function poll() {
            check() && setTimeout(fn, 0) || setTimeout(poll, 100);
        })();
    }

    function changeColor() {
        console.log("开始换肤" + (new Date()).valueOf())
        var styleSheets = doc.styleSheets
        var styleSheet;
        //预处理，兼容原先color配置文件，16进制转换为rgb，支持rgba和rgb逗号后需要空格，不支持16进制透明度
        //后续支持css全局变量可以按照需求转变
        var newColorData = {}
        for (var key in colorData) {
            var newkey;
            if (key.substr(0, 1) == "#") {
                key = key.substring(1);
                key = key.toLowerCase();
                var b = new Array();
                for (var x = 0; x < 3; x++) {
                    b[0] = key.length == 6 ? key.substr(x * 2, 2) : key.substr(x * 1, 1) + key.substr(x * 1, 1);
                    b[3] = "0123456789abcdef";
                    b[1] = b[0].substr(0, 1);
                    b[2] = b[0].substr(1, 1);
                    b[20 + x] = b[3].indexOf(b[1]) * 16 + b[3].indexOf(b[2])
                }
                newkey = "rgb\\(" + b[20] + ",\\s" + b[21] + ",\\s" + b[22] + "\\)"
                newColorData[newkey] = colorData['#' + key]
            } else if (key.substr(0, 1) == "@") {
                switch (key) {
                    case "@primary-color":
                        newColorData["rgb\\(53,\\s152,\\s219\\)"] = colorData[key];
                        break;
                    case "@success-color":
                        newColorData["rgb\\(33,\\s202,\\s0\\)"] = colorData[key];
                        break;
                    case "@error-color":
                        newColorData["rgb\\(253,\\s69,\\s69\\)"] = colorData[key];
                        break;
                    case "@warn-color":
                        newColorData["rgb\\(255,\\s163,\\s2\\)"] = colorData[key];
                        break;
                    case "@tFont-color":
                        newColorData["rgb\\(118,\\s121,\\s124\\)"] = colorData[key];
                        break;
                    case "@iFont-color":
                        newColorData["rgb\\(44,\\s48,\\s52\\)"] = colorData[key];
                        break;
                    case "@fFont-color":
                        newColorData["rgb\\(201,\\s201,\\s201\\)"] = colorData[key];
                        break;
                    case "@line-color":
                        newColorData["rgb\\(223,\\s223,\\s223\\)"] = colorData[key];
                        break;
                    case "@select-color":
                        newColorData["rgb\\(228,\\s245,\\s255\\)"] = colorData[key];
                        break;
                    case "@light-gray":
                        newColorData["rgb\\(248,\\s248,\\s248\\)"] = colorData[key];
                        break;
                    case "@white-color":
                        newColorData["rgb\\(255,\\s255,\\s255\\)"] = colorData[key];
                        break;
                    case "@dis-color":
                        newColorData["rgb\\(239,\\s239,\\s239\\)"] = colorData[key];
                        break;
                    case "@primary-disFont":
                        newColorData["rgb\\(154,\\s197,\\s234\\)"] = colorData[key];
                        break;
                    case "@hover-primary":
                        newColorData["rgb\\(37,\\s136,\\s202\\)"] = colorData[key];
                        break;
                    case "@nav-bg":
                        newColorData["rgb\\(49,\\s59,\\s70\\)"] = colorData[key];
                        break;
                    case "@nav-active":
                        newColorData["rgb\\(38,\\s46,\\s55\\)"] = colorData[key];
                        break;
                    default:
                        break;
                }
            } else if (key.substr(0, 3) == "rgb") {
                newkey = key.replace(/[(]/g, "\\(").replace(/[ ]/g, "\\s").replace(/[)]/g, "\\)")
                newColorData[newkey] = colorData[key]
            }

        }
        var regtest;
        var longStr = ''
        for (let i = 0; i < styleSheets.length; i++) {
            styleSheet = styleSheets[i]
            for (let j = 0; j < styleSheet.cssRules.length; j++) {
                longStr += styleSheet.cssRules[j].cssText + "&"
            }
        }
        for (var key in newColorData) {
            regtest = new RegExp(key, 'g')
            longStr = longStr.replace(regtest, newColorData[key])
        }
        longStr = longStr.split('&')
        var flag = 0
        for (let i = 0; i < styleSheets.length; i++) {
            styleSheet = styleSheets[i]
            for (let j = 0; j < styleSheet.cssRules.length; j++) {
                styleSheet.insertRule(longStr[flag++], j)
                styleSheet.deleteRule(j + 1)
            }
        }
        console.log("换肤结束" + (new Date()).valueOf())
    }
    cssReady(changeColor)
    client.onload = function () {
        changeColor()
    }
}
/**@augments
 * @method encryption()  加密
 * @param {String}
 * publicKey:公钥；password:密码
 */
export function encryption(publicKey, password) {
    let encryptor = new JSEncrypt()
    encryptor.setPublicKey(publicKey)
    let psw = encryptor.encrypt(password)
    return psw
}
/**
 * 短横线命名kebab-case 转换 驼峰命名CamelCase
 * @param {*} str 
 * @returns 
 */
export function underlineToHump(str) {
    // 如果首字母是-，执行 replace 时会多一个-，这里需要去掉
    if (str.slice(0, 1) === '-') {
        str = str.slice(1);
    }
    return str.replace(/([^-])(?:-+([^-]))/g, function ($0, $1, $2) {
        return $1 + $2.toUpperCase();
    });
}
/**
 * 驼峰命名CamelCase 转换 短横线命名kebab-case
 * @param {*} str 
 * @returns 
 */
export function humpToUnderline(str) {
    let temp = str.replace(/[A-Z]/g, function (match) {
        return "-" + match.toLowerCase();
    });
    // 如果首字母是大写，执行replace时会多一个-，这里需要去掉
    if (temp.slice(0, 1) === '-') {
        temp = temp.slice(1);
    }
    return temp;
}